﻿using EMall.Application;
using EMall.ProductService.Brands;
using EMall.ProductService.Categories;
using EMall.Query;
using EMall.Uow;

namespace EMall.ProductService.Products
{
    public class ProductAppService : ApplicationService, IProductAppService
    {
        private readonly IProductRepository _productRepository;
        private readonly ICategoryRepository _categoryRepository;
        private readonly IBrandRepository _brandRepository;
        public ProductAppService(
            IProductRepository productRepository,
            ICategoryRepository categoryRepository,
            IBrandRepository brandRepository)
        {
            _productRepository = productRepository;
            _categoryRepository = categoryRepository;
            _brandRepository = brandRepository;
        }
        [UnitOfWork]
        public async Task CreateAsync(CreateProductDto input)
        {
            var category = await _categoryRepository.GetAsync(input.CategoryId);
            var brand = await _brandRepository.GetAsync(input.BrandId);
            var product = new Product(input.Name, input.Model, input.Description, category.Id, brand.Id,input.IsActive);
            foreach (var picture in input.Pictures)
            {
                product.AddPicture(picture.Url);
            }
            await _productRepository.AddAsync(product);
        }
        [UnitOfWork]
        public async Task UpdateAsync(UpdateProductDto input)
        {
            var category = await _categoryRepository.GetAsync(input.CategoryId);
            var brand = await _brandRepository.GetAsync(input.BrandId);
            var product = await _productRepository.GetAsync(input.Id);
            product.Update(input.Name, input.Model, input.Description, category.Id, brand.Id, input.IsActive);
            var addPictures = input.Pictures.Where(o => !o.Id.HasValue);
            foreach (var picture in addPictures)
            {
                product.AddPicture(picture.Url);
            }
            var updatePictures = input.Pictures.Where(o => o.Id.HasValue);
            foreach (var picture in updatePictures)
            {
                product.UpdatePicture(picture.Id!.Value, picture.Url);
            }
            var removePictrueIds = product.Pictures.Where(o => !updatePictures.Select(s => s.Id!.Value).Contains(o.Id)).Select(o => o.Id);
            foreach (var pictureId in removePictrueIds)
            {
                product.RemovePicture(pictureId);
            }
        }
        [UnitOfWork]
        public async Task DeleteAsync(DeleteProductDto input)
        {
            var product = await _productRepository.GetAsync(input.Id);
            await _productRepository.RemoveAsync(product);
        }
        public async Task<ProductDto> GetAsync(int id)
        {
            var product = await QueryService.GetAsync<Product, int>(id);
            return Mapper.Map<ProductDto>(product);
        }
        public async Task<IPagedList<ProductListDto>> GetPagedListAsync(GetProductListPagingAndSortingQueryDto input)
        {
            var pagedData = await QueryService.GetQueryable<Product>()
               .Sorting(input.Sorting)
               .ToPagedListAsync(input.PageIndex, input.PageSize);
            return Mapper.Map<Product, ProductListDto>(pagedData);
        }
    }
}